/*******************************************************************************
 * CBPageViewController.m
 * ComicsBlog
 *
 * Adrien Bougouin <adrien.bougouin@gmail.com>
 */

#import "CBPageViewController.h"
#import "CBNewsViewController.h"

#import "../view/CBUneItemView.h"
#import "../view/CBNewsTableViewCell.h"

@implementation CBPageViewController

- (id) initWithCategory:(NSUInteger) category
             homeTarget:(id) homeTarget
           homeSelector:(SEL) homeSelector {
  self = [super init];

  if(self) {
    _category = category;
    _isLoading = YES;
    _page = [[CBPage alloc] initWithCategory:category];
    _uneSeparator = nil;
    _uneItem = nil;
    _newsSeparator = nil;
    _moreNewsCell = [[CBMoreNewsTableViewCell alloc] init];

    // stop the spinner of the last cell of the UITableView
    // and reload the UITableView
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(pageUpdated)
                                                 name:CBPageUpdatedNotificationName
                                               object:nil];
    // stop the spinner of the last cell of the UITableView
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(pageError)
                                                 name:CBPageErrorNotificationName
                                               object:nil];

    [self configureViewWithTitle:titles[_category]
                      homeTarget:homeTarget
                    homeSelector:homeSelector];
    [_page loadNewsFrom:1 length:CBPageNumberOfNewsToLoad];
  }

  return self;
}

- (void) dealloc {
  [super dealloc];

  [_uneSeparator  release];
  [_uneItem       release];
  [_newsSeparator release];
  [_page          release];
  [_newsView      release];
  [_moreNewsCell  release];
}

- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation {
  UIView *uneItemView = [_uneItem contentView];
  UIScrollView *uneView = (UIScrollView *) [[uneItemView subviews] objectAtIndex:0];

  if(interfaceOrientation == UIInterfaceOrientationPortrait
     || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
    [uneView setPagingEnabled:YES];
  } else {
    [uneView setPagingEnabled:NO];
  }

  return YES;
}

- (void) pageUpdated {
  _isLoading = NO;
  [_moreNewsCell stopSpinning];
  [_newsView reloadData];
}

- (void) pageError {
  NSString    *errorTitle   = @"Echec";
  NSString    *errorMessage = [_page lastErrorMessage];
  UIAlertView *errorPopUp   = [[UIAlertView alloc] initWithTitle:errorTitle
                                                         message:errorMessage
                                                        delegate:nil
                                               cancelButtonTitle:@"OK"
                                               otherButtonTitles:nil];

  [_moreNewsCell stopSpinning];

  // memory management
  [errorPopUp autorelease];

  [errorPopUp show];
}

- (void) configureViewWithTitle:(NSString *) title
                     homeTarget:(id) homeTarget
                   homeSelector:(SEL) homeAction {
  // add a new autorelease pool to the stack
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

  NSBundle *mainBundle = [NSBundle mainBundle];
  NSString *resources = [[mainBundle bundlePath] stringByAppendingString:@"/"];
  CGRect zeroFrame = CGRectMake(0, 0, 0, 0);
  UIColor *cbColor = [[UIColor alloc] initWithRed:(47.0 / 255.0)
                                            green:(70.0 / 255.0)
                                             blue:(85.0 / 255.0)
                                            alpha:1.0];
  UIViewController *newsViewController = [[UIViewController alloc] init];
  UINavigationBar *navigationBar = [self navigationBar];
  UINavigationItem *navigationItem = [newsViewController navigationItem];
  NSString *homeImagePath = [resources stringByAppendingString:CBPageHomeImage];
  UIImage *homeImage = [[UIImage alloc] initWithContentsOfFile:homeImagePath];
  UIBarButtonItem *homeItem = [[UIBarButtonItem alloc] initWithImage:homeImage
                                                               style:UIBarButtonItemStyleBordered
                                                              target:homeTarget
                                                              action:homeAction];
  UIBarButtonItem *refreshItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh
                                                                               target:self
                                                                               action:@selector(reload)];
  _newsView = [[UITableView alloc] initWithFrame:zeroFrame
                                           style:UITableViewStylePlain];

  // configuration
  [newsViewController setTitle:title];
  [navigationBar setTintColor:cbColor];
  [navigationItem setLeftBarButtonItem:homeItem];
  [navigationItem setRightBarButtonItem:refreshItem];
  [_newsView setDelegate:self];
  [_newsView setDataSource:self];

  [newsViewController setView:_newsView];
  [self pushViewController:newsViewController animated:YES];

  // memory management
  [cbColor            release];
  [newsViewController release];
  [homeImage          release];
  [homeItem           release];
  [refreshItem        release];

  // delete the local autorelease pool then dealloc autoreleased objects used by
  // the method
  [pool release];
}

- (void) reload {
  [_uneSeparator  release];
  [_uneItem       release];
  [_newsSeparator release];
  [_page release];

  _uneSeparator = nil;
  _uneItem = nil;
  _newsSeparator = nil;
  _page = [[CBPage alloc] initWithCategory:_category];

  [_newsView reloadData];
  [_page loadNewsFrom:1 length:CBPageNumberOfNewsToLoad];
}

- (void) uneItemSelected:(CBUneItemView *) uneItem {
  NSUInteger index = [uneItem index];
  CBNews *news = [_page newsAtIndex:index];
  CBNewsViewController *newsView = [[CBNewsViewController alloc] initWithNews:news];

  [self pushViewController:newsView animated:YES];

  // memory management
  [newsView release];
}

//==============================================================================
// UITableViewDelegate
//==============================================================================

- (void)        tableView:(UITableView *) tableView
  didSelectRowAtIndexPath:(NSIndexPath *) indexPath {
  NSUInteger index = [indexPath indexAtPosition:1];
  NSInteger count = [self tableView:_newsView numberOfRowsInSection:0];

  if(index == (count - 1)) {
    if(!_isLoading) {
      _isLoading = YES;

      [_moreNewsCell startSpinning];

      [_page loadNewsFrom:([_page numberOfNews] + 1)
                   length:CBPageNumberOfNewsToLoad];
    }
  // do not select the first three items (une label + une + other news label)
  } else if(index > 2) {
    CBNews *news = [_page newsAtIndex:index + (CBPageNumberOfUneNews - 3)];
    CBNewsViewController *newsView = [[CBNewsViewController alloc] initWithNews:news];

    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    [self pushViewController:newsView animated:YES];

    // memory management
    [newsView release];
  }
}

//==============================================================================
// UITableViewDataSource
//==============================================================================

- (UITableViewCell *) tableView:(UITableView *) tableView
          cellForRowAtIndexPath:(NSIndexPath *) indexPath {
  NSBundle *mainBundle = [NSBundle mainBundle];
  NSString *resources = [[mainBundle bundlePath] stringByAppendingString:@"/"];
  CGRect screenFrame = [[UIScreen mainScreen] bounds];;
  NSUInteger index = [indexPath indexAtPosition:1];
  NSInteger count = [self tableView:_newsView numberOfRowsInSection:0];
  UITableViewCell *cell = nil;
  float ratio = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? CBPageIPadRatio: 1.0;

  // une label
  if(index == 0) {
    if(!_uneSeparator) {
      // add a new autorelease pool to the stack
      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

      NSUInteger cellStyle = UITableViewCellStyleDefault;
      CGRect imageFrame = CGRectMake(0,
                                     0,
                                     CGRectGetWidth(screenFrame) / ratio,
                                     CBPageSeparatorHeight);
      NSString *backgroundPath = [resources stringByAppendingString:CBPageSeparatorImage];
      UIImage *background = [[UIImage alloc] initWithContentsOfFile:backgroundPath];
      UIImageView *backgroundView = [[UIImageView alloc] initWithFrame:imageFrame];
      NSString *labelPath = [resources stringByAppendingString:CBPageUneLabelImage];
      UIImage *label = [[UIImage alloc] initWithContentsOfFile:labelPath];
      UIImageView *labelView = [[UIImageView alloc] initWithFrame:imageFrame];

      _uneSeparator = [[UITableViewCell alloc] initWithStyle:cellStyle
                                             reuseIdentifier:@"uneLabel"];

      // configuration
      [backgroundView setImage:background];
      [backgroundView setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
      [labelView setImage:label];
      [labelView setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin];
      [_uneSeparator setSelectionStyle:UITableViewCellSelectionStyleNone];
      [[_uneSeparator contentView] addSubview:backgroundView];
      [[_uneSeparator contentView] addSubview:labelView];

      // memory management
      [background     release];
      [backgroundView release];
      [label          release];
      [labelView      release];

      // delete the local autorelease pool then dealloc autoreleased objects
      // used by the method
      [pool release];
    }

    cell = [_uneSeparator retain];
  } else if(index == 1) {
    if(!_uneItem) {
      // add a new autorelease pool to the stack
      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

      NSUInteger cellStyle = UITableViewCellStyleDefault;
      NSUInteger uneNewsIndex = 0;
      CGRect uneFrame = CGRectMake(0,
                                   0,
                                   CGRectGetWidth(screenFrame) / ratio,
                                   CBPageUneHeight * ratio);
      CGFloat uneNewsWidth = CGRectGetWidth(screenFrame);
      CGFloat uneNewsHeight = CBPageUneHeight * ratio;
      UIScrollView *uneView = [[UIScrollView alloc] initWithFrame:uneFrame];

      _uneItem = [[UITableViewCell alloc] initWithStyle:cellStyle
                                    reuseIdentifier:@"uneItem"];

      // configuration
      if([self interfaceOrientation] == UIInterfaceOrientationPortrait
         || [self interfaceOrientation] == UIInterfaceOrientationPortraitUpsideDown) {
        [uneView setPagingEnabled:YES];
      } else {
        [uneView setPagingEnabled:NO];
      }
      // add items
      for(uneNewsIndex;
          uneNewsIndex < CBPageNumberOfUneNews
          && uneNewsIndex < [_page numberOfNews];
          ++uneNewsIndex) {
        CGRect uneNewsFrame = CGRectMake(uneNewsWidth * uneNewsIndex,
                                         0,
                                         uneNewsWidth,
                                         uneNewsHeight);
        CBNews *news = [_page newsAtIndex:uneNewsIndex];
        CBUneItemView *uneNews = [[CBUneItemView alloc] initWithFrame:uneNewsFrame
                                                                 news:news
                                                                index:uneNewsIndex];

        [uneView addSubview:uneNews];
        [uneNews addTarget:self
                    action:@selector(uneItemSelected:)
                  forControlEvents:UIControlEventTouchUpInside];

        // memory management
        [uneNews release];
      }

      [uneView setContentSize:CGSizeMake(uneNewsWidth * uneNewsIndex,
                                         uneNewsHeight)];
      [uneView setIndicatorStyle:UIScrollViewIndicatorStyleBlack];
      [uneView setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
      [[_uneItem contentView] addSubview:uneView];

      // memory management
      [uneView release];

      // delete the local autorelease pool then dealloc autoreleased objects
      // used by the method
      [pool release];
    }

    cell = [_uneItem retain];
  // other news label
  } else if(index == 2) {
    if(!_newsSeparator) {
      // add a new autorelease pool to the stack
      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

      NSUInteger cellStyle = UITableViewCellStyleDefault;
      CGRect imageFrame = CGRectMake(0,
                                     0,
                                     CGRectGetWidth(screenFrame) / ratio,
                                     CBPageSeparatorHeight);
      NSString *backgroundPath = [resources stringByAppendingString:CBPageSeparatorImage];
      UIImage *background = [[UIImage alloc] initWithContentsOfFile:backgroundPath];
      UIImageView *backgroundView = [[UIImageView alloc] initWithFrame:imageFrame];
      NSString *labelPath = [resources stringByAppendingString:CBPageNewsLabelImage];
      UIImage *label = [[UIImage alloc] initWithContentsOfFile:labelPath];
      UIImageView *labelView = [[UIImageView alloc] initWithFrame:imageFrame];

      _newsSeparator = [[UITableViewCell alloc] initWithStyle:cellStyle
                                              reuseIdentifier:@"newsLabel"];

      // configuration
      [backgroundView setImage:background];
      [backgroundView setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
      [labelView setImage:label];
      [labelView setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin];
      [_newsSeparator setSelectionStyle:UITableViewCellSelectionStyleNone];
      [[_newsSeparator contentView] addSubview:backgroundView];
      [[_newsSeparator contentView] addSubview:labelView];

      // memory management
      [background     release];
      [backgroundView release];
      [label          release];
      [labelView      release];

      // delete the local autorelease pool then dealloc autoreleased objects
      // used by the method
      [pool release];
    }

    cell = [_newsSeparator retain];
  } else if(index == (count - 1)) {
    return _moreNewsCell;
  } else {
    CBNews *news = [_page newsAtIndex:(index + (CBPageNumberOfUneNews - 3))];

    cell = [[CBNewsTableViewCell alloc] initWithNews:news];
  }

  [cell setAutoresizingMask:UIViewAutoresizingFlexibleWidth];

  // memory management
  [cell autorelease];

  return cell;
}

- (CGFloat)     tableView:(UITableView *) tableView
  heightForRowAtIndexPath:(NSIndexPath *) indexPath {
  NSUInteger index = [indexPath indexAtPosition:1];
  NSInteger count = [self tableView:_newsView numberOfRowsInSection:0];
  float ratio = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? CBPageIPadRatio: 1.0;

  if(index == 0 || index == 2) {
    return CBPageSeparatorHeight;
  } else if(index == 1) {
    return CBPageUneHeight * ratio;
  } else if(index == count - 1) {
    return CBMoreNewsHeight;
  } else {
    return CBPageNewsHeight;
  }
}

// WARNING works only because CBPageNumberOfNewsToLoad > 5
- (NSInteger) tableView:(UITableView *) tableView
  numberOfRowsInSection:(NSInteger) section {
  NSInteger count = [_page numberOfNews];

  if(count > 0) {
    if(count <= CBPageNumberOfUneNews) {
      count = 2;
    } else {
      // une label
      // une item (CBPageNumberOfUneNews news)
      // other news label
      // more news item
     count -= (CBPageNumberOfUneNews - 4);
    }
  }

  return count;
}

@end

